// 定义类SockeService，并定义成单例设计模式
export default class SocketService {
  /*
    单例
  */
  static instance = null
  static get Instance() {
    if (!this.instance) {
      this.instance = new SocketService()
    }
    return this.instance
  }

  // 和服务端连接的socket对象
  ws = null

  // 标记是否链接成功
  connected = false
  // 记录重试连接的次数
  sendRetryCount = 0        // retry：重试
  // 重新连接尝试的次数
  againRetryCount = 0       // again：重新

  // 存储回调函数
  callBackMapping = {}

  //定义连接服务端的方法
  connect() {   
    // 连接服务器
    if (!window.WebSocket) {
      return console.log('您的浏览器不支持WebSocket')
    }

    this.ws = new WebSocket('ws://127.0.0.1:9999')
    // 连接成功的事件
    this.ws.onopen = () => {
      console.log('连接服务端成功!')
      this.connected = true
      this.sendRetryCount = 0
      this.againRetryCount = 0
    }

    // 连接失败的事件
    this.ws.onclose = () => {
      console.log('连接服务端失败!')
      this.connected = false
      this.againRetryCount++
      // 如果服务端没有打开服务会一直发起连接，直到连接成功!
      setTimeout(() => {
        this.connect()
      }, this.againRetryCount * 500);
    }

    // 得到服务端发送过来的数据
    this.ws.onmessage = (msg) => {  // 这里的msg是一个MessageEvent事件对象，真正的数据在data字段中
      console.log('收到服务端推送的数据了', JSON.parse(msg.data))

      // 真正服务端发送过来的原始数据，在msg中的data字段中
      const data = JSON.parse(msg.data)
      const socketType = data.socketType
      // 判断回调函数是否存在
      if (this.callBackMapping[socketType]) {
        const action = data.action  // 代表某项行为
        if (action === 'getData') {
          const newData = JSON.parse(data.data) // data中的data字段才是图表的相关数据
          this.callBackMapping[socketType].call(this, newData)

        } else if (action === 'fullScreen') {
          this.callBackMapping[socketType].call(this, data)

        } else if (action === 'themeChange') {
          console.log('主题切换：', data)
          this.callBackMapping[socketType].call(this, data)
        }
      }
    }
  }

  // 回调函数的注册
  registerCallBack (socketType, callBack) {
    console.log('注册成功事件')
    this.callBackMapping[socketType] = callBack;
  }

  // 取消某一个回调函数
  unRegisterCallBack (socketType) {
    this.callBackMapping[socketType] = null;
  }

  // 发送数据的方法
  send (data) {
    // 如果连接就发送数据给服务端
    if (this.connected) {
      this.ws.send(JSON.stringify(data))
    } else {
      this.sendRetryCount++
      setTimeout(() => {
        this.send(data)  // 再次尝试发送数据
      }, this.sendRetryCount * 500)
    }
  }
}